
`include "common_header.verilog"

//  *************************************************************************
//   File : dskw_buf_rd.v
//  *************************************************************************
//   This program is controlled by a written license agreement.
//   Unauthorized Reproduction or Use is Expressly Prohibited. 
// 
//  Copyright (c) 2005 Morethanip GmbH
//  info@morethanip.com
//  *************************************************************************
//  Version: $Id: dskw_buf_rd.v,v 1.4 2006/09/07 11:45:17 dk Exp $ 
//  Author : Muhammad Anisur Rahman
//  *************************************************************************
//  Description:
// 
//   10 Gigabit Ethernet XGXS Receive Synchronization
// 
//  *************************************************************************

module dskw_buf_rd (
   
   reset,
   clk,
  `ifdef USE_CLK_ENA
   clk_ena,
  `endif   
   enable_deskew,
   deskew_error,
   align_done,
   dskw_aempty0,
   dskw_aempty1,
   dskw_aempty2,
   dskw_aempty3,
   ff_rden);

input   reset;                  //  Asynchronous Reset
input   clk;                    //  156.25MHz Line Clock
`ifdef USE_CLK_ENA
input   clk_ena;
`endif 
input   enable_deskew;          //  Enable Lane Deskew 
input   deskew_error;           //  Lane Alignment Error 
input   align_done;             //  Alignment completed  
input   dskw_aempty0;           //  Lane 0 Deskew Buffer Almost Full
input   dskw_aempty1;           //  Lane 1 Deskew Buffer Almost Full
input   dskw_aempty2;           //  Lane 2 Deskew Buffer Almost Full
input   dskw_aempty3;           //  Lane 3 Deskew Buffer Almost Full
output  ff_rden;                //  Buffer Write Enable

reg     ff_rden; 

parameter STM_TYP_IDLE       = 3'h0;
parameter STM_TYP_WAIT_BUF   = 3'h1;
parameter STM_TYP_WAIT_ALIGN = 3'h2;
parameter STM_TYP_BUF_READ   = 3'h3;
parameter STM_TYP_STOP_READ  = 3'h4;

reg     [2:0] nextstate; 
reg     [2:0] state; 

always @(posedge reset or posedge clk)
   begin : process_1
   if (reset == 1'b 1)
      begin
      state <= STM_TYP_IDLE;   
      end
   else
      begin
      
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif      
      
                state <= nextstate;   
      
         `ifdef USE_CLK_ENA
            end
         `endif            
      
      end
   end

always @(state or enable_deskew or align_done or dskw_aempty0 or dskw_aempty1
 or dskw_aempty2 or dskw_aempty3 or deskew_error)
   begin : process_2
   case (state)
   STM_TYP_IDLE:
      begin
      if (enable_deskew == 1'b 1)
         begin
         nextstate = STM_TYP_WAIT_BUF;   
         end
      else
         begin
         nextstate = STM_TYP_IDLE;   
         end
      end
   STM_TYP_WAIT_BUF:
      begin
      if (dskw_aempty0 == 1'b 0 & dskw_aempty1 == 1'b 0 & 
      dskw_aempty2 == 1'b 0 & dskw_aempty3 == 1'b 0)
         begin
         nextstate = STM_TYP_WAIT_ALIGN;   
         end
      else
         begin
         nextstate = STM_TYP_WAIT_BUF;   
         end
      end
   STM_TYP_WAIT_ALIGN:
      begin
      if (deskew_error==1'b1)
         begin
         nextstate = STM_TYP_STOP_READ;
         end
      else if (align_done == 1'b 1)
         begin
         nextstate = STM_TYP_BUF_READ;   
         end
      else
         begin
         nextstate = STM_TYP_WAIT_ALIGN;   
         end
      end
   STM_TYP_BUF_READ:
      begin
      if (align_done == 1'b 0)
         begin
         nextstate = STM_TYP_STOP_READ;   
         end
      else
         begin
         nextstate = STM_TYP_BUF_READ;   
         end
      end
   STM_TYP_STOP_READ:
      begin
      if (dskw_aempty0 == 1'b 1 & dskw_aempty1 == 1'b 1 & 
      dskw_aempty2 == 1'b 1 & dskw_aempty3 == 1'b 1)
         begin
         nextstate = STM_TYP_IDLE;   
         end
      else
         begin
         nextstate = STM_TYP_STOP_READ;   
         end
      end
   default
      begin
      nextstate = STM_TYP_IDLE;
      end
   endcase
   end

//  Buffer Control
//  --------------

always @(posedge reset or posedge clk)
   begin : process_3
   if (reset == 1'b 1)
      begin
      ff_rden <= 1'b 0;   
      end
   else
      begin
      
         `ifdef USE_CLK_ENA
            if(clk_ena == 1'b 1)
            begin
         `endif      
      
              if (nextstate == STM_TYP_WAIT_ALIGN | nextstate == STM_TYP_BUF_READ)
                 begin
                 ff_rden <= 1'b 1;   
                 end
              else
                 begin
                 ff_rden <= 1'b 0;   
                 end
      
         `ifdef USE_CLK_ENA
            end
         `endif      
      
      end
   end

endmodule // module dskw_buf_rd